package com.xiyu.service.service.elder;

import com.xiyu.service.enums.elder.register.ElderGoOutStatusEnum;
import com.xiyu.service.model.elder.register.ElderGoOutDraft;
import com.xiyu.service.vo.elder.goOut.GoOutUpdateStatusInput;
import com.xiyu.service.vo.elder.goOut.GoOutGetOutput;
import com.xiyu.service.vo.elder.goOut.GoOutUpdateInput;
import com.xiyu.service.vo.elder.goOut.GoOutCreateInput;
import com.xiyu.service.model.elder.register.ElderGoOut;
import com.xiyu.service.repository.elder.register.ElderGoOutRepository;
import com.xiyu.service.vo.elder.goOut.GoOutPageQueryOutput;
import com.xiyu.service.vo.elder.goOut.GoOutPageQueryInput;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.babyfish.jimmer.Page;
import java.util.*;

import org.springframework.transaction.annotation.Transactional;
import com.xiyu.service.framework.web.web.core.pojo.PageResult;
import com.xiyu.service.convert.elder.GoOutConvert;

import static com.xiyu.service.framework.exception.util.ServiceExceptionUtil.exception;
import static com.xiyu.service.errorCode.elder.GoOutErrorCode.*;

/**
 * 外出登记 Service 实现类
 */
@Service
@Validated
public class GoOutServiceImpl implements GoOutService {

    @Resource
    private ElderGoOutRepository elderGoOutRepository;


    @Override
    public PageResult<GoOutPageQueryOutput> pageQuery(GoOutPageQueryInput inputVO) {
        Page<ElderGoOut> pageElderGoOut = elderGoOutRepository.pageQuery(inputVO);
        List<GoOutPageQueryOutput> listElderGoOut = GoOutConvert.INSTANCE.pageQueryOutputConvert(pageElderGoOut.getRows());
        return new PageResult<>(listElderGoOut, pageElderGoOut.getTotalRowCount());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long create(GoOutCreateInput inputVO) {
        ElderGoOut newElderGoOut = GoOutConvert.INSTANCE.createInputConvert(inputVO);
        newElderGoOut = elderGoOutRepository.insert(newElderGoOut);
        return newElderGoOut.id();

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean update(GoOutUpdateInput inputVO) {
        Optional<ElderGoOut> optionalOldElderGoOut = elderGoOutRepository.findById(inputVO.getId());
        if(!optionalOldElderGoOut.isPresent()){
            throw exception(ELDER_GO_OUT_NOT_EXIST);
        }
        ElderGoOut updateElderGoOut = GoOutConvert.INSTANCE.updateInputConvert(inputVO);
        elderGoOutRepository.update(updateElderGoOut);
        return true;
    }

    @Override
    public GoOutGetOutput get(Long id) {
        Optional<ElderGoOut> optionalElderGoOut = elderGoOutRepository.findDetailById(id);
        if(!optionalElderGoOut.isPresent()){
            throw exception(ELDER_GO_OUT_NOT_EXIST);
        }
        return GoOutConvert.INSTANCE.getOutputConvert(optionalElderGoOut.get());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateStatus(GoOutUpdateStatusInput inputVO) {
        Optional<ElderGoOut> optionalElderGoOut = elderGoOutRepository.findById(inputVO.getId());
        if(!optionalElderGoOut.isPresent()){
            throw exception(ELDER_GO_OUT_NOT_EXIST);
        }
        ElderGoOut elderGoOut = optionalElderGoOut.get();
        if(inputVO.getStatus().equals(ElderGoOutStatusEnum.GO_OUT.getValue())){
            if(!elderGoOut.status().equals(ElderGoOutStatusEnum.NOT_GO_OUT.getValue())){
                throw exception(ELDER_GO_OUT_NOT_GO_CAN_GO);
            }
            elderGoOut = ElderGoOutDraft.$.produce(elderGoOut, draft -> {
                draft.setStatus(ElderGoOutStatusEnum.GO_OUT.getValue());
            });
        } else if(inputVO.getStatus().equals(ElderGoOutStatusEnum.CANCEL.getValue())) {
            if(!elderGoOut.status().equals(ElderGoOutStatusEnum.NOT_GO_OUT.getValue())){
                throw exception(ELDER_GO_OUT_NOT_GO_CAN_CANCEL);
            }
            elderGoOut = ElderGoOutDraft.$.produce(elderGoOut, draft -> {
                draft.setStatus(ElderGoOutStatusEnum.CANCEL.getValue());
            });
        } else if(inputVO.getStatus().equals(ElderGoOutStatusEnum.RETURN.getValue())){
            if(!elderGoOut.status().equals(ElderGoOutStatusEnum.GO_OUT.getValue())){
                throw exception(ELDER_GO_OUT_GO_CAN_RETURN);
            }
            elderGoOut = ElderGoOutDraft.$.produce(elderGoOut, draft -> {
                draft.setStatus(ElderGoOutStatusEnum.RETURN.getValue())
                        .setReturnTime(inputVO.getReturnTime().toString());
            });
        }
        elderGoOutRepository.update(elderGoOut);
        return true;
    }

}
